﻿package com.reyco1.gadget  
{
	/*
	Imports
	*/
	import flash.events.MouseEvent;
	import com.reyco1.util.IntervalUtil;
	import com.reyco1.events.IntervalEvent;
	import com.reyco1.events.ButtonEvent;
	import com.reyco1.extension.StandardExtension
	/*
	Class
	*/
	public final class EnhancedButton extends StandardExtension
	{		
		/*
		Variables
		*/
		private var mcButton:*;
		private var objParams:Object;
		private var objFunctions:Object;
		private var numDelay:Number;
		private var clickedInterval:IntervalUtil;
		/*
		Constructor
		*/
		
		/**
		 * EnhancedButton constructor
		 * @param $btn : DisplayObject to apply button character to
		 * @param $useHandCursor : Boolean specifying weather the hand cursor should be used or not
		 * @return 
		 * 
		 */		
		public function EnhancedButton($btn:*, $useHandCursor:Boolean = true)
		{
			this.objParams = new Object();
			this.objFunctions = new Object();
			this.mcButton = $btn;
			this.mcButton.buttonMode = true;
			this.mcButton.useHandCursor = $useHandCursor;
		}
		/*
		Functions
		*/
		
		// add button listener
		
		/**
		 * Adds a specified com.reyco1.events.ButtonEvent event
		 * @param $event : com.reyco1.events.ButtonEvent
		 * @param $function : function to run upon listening the the specificed event
		 * @param $params : params to cary along to the listener
		 * 
		 */		
		public function addButtonListener($event:String, $function:Function, $params:Object = null):void
		{
			
			$params = ($params == null) ? new Object() : $params 
			
			switch($event)
			{
				case ButtonEvent.CLICK:
				this.objParams.clickParams = $params;
				this.objFunctions.clickFunction = $function;
				this.mcButton.addEventListener(MouseEvent.CLICK, this.addMouseInteraction);
				break;
				
				case ButtonEvent.UP:
				this.objParams.upParams = $params;
				this.objFunctions.upFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_UP, this.addMouseInteraction);
				break;
				
				case ButtonEvent.DOWN:
				this.objParams.downParams = $params;
				this.objFunctions.downFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_DOWN, this.addMouseInteraction);
				break;
				
				case ButtonEvent.OVER:
				this.objParams.overParams = $params;
				this.objFunctions.overFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_OVER, this.addMouseInteraction);
				break;
				
				case ButtonEvent.OUT:
				this.objParams.outParams = $params;
				this.objFunctions.outFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_OUT, this.addMouseInteraction);
				break;
				
				case ButtonEvent.DOUBLE_CLICK:
				this.mcButton.doubleClickEnabled = true;
				this.objParams.doubleClickParams = $params;
				this.objFunctions.doubleClickFunction = $function;
				this.mcButton.addEventListener(MouseEvent.DOUBLE_CLICK, this.addMouseInteraction);
				break;
				
				case ButtonEvent.RELEASE_OUTSIDE:
				this.objParams.releaseOutsideParams = $params;
				this.objFunctions.releaseOutsideFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_DOWN, this.checkForReleaseOutside);
				break;
				
				case ButtonEvent.DRAG_OVER:
				this.objParams.dragOverParams = $params;
				this.objFunctions.dragOverFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_OVER, this.checkForDragOver);
				break;
				
				case ButtonEvent.DRAG_OUT:
				this.objParams.dragOutParams = $params;
				this.objFunctions.dragOutFunction = $function;
				this.mcButton.addEventListener(MouseEvent.MOUSE_OUT, this.checkForDragOut);
				break;
				
				case ButtonEvent.WHILE_CLICKED:
				this.objParams.whileClickedParams = $params;
				this.objFunctions.whileClickedFunction = $function;
				this.numDelay = ($params.delay) ? $params.delay : 0.1
				this.mcButton.addEventListener(MouseEvent.MOUSE_DOWN, this.initiateClickedInterval);
				this.clickedInterval = new IntervalUtil("pressedTimer", this.timerHandler);
				this.clickedInterval.outputSilenced = true;
				break;
			}
		}
		
		// remove button listener
		
		/**
		 * Removes a specified com.reyco1.events.ButtonEvent event
		 * @param $event : com.reyco1.events.ButtonEvent
		 * 
		 */
		public function removeButtonListener($event:String):void
		{
			switch($event)
			{
				case ButtonEvent.CLICK:
				this.objParams.clickParams = null;
				this.objFunctions.clickFunction = null;
				this.mcButton.removeEventListener(MouseEvent.CLICK, this.addMouseInteraction);
				break;
				
				case ButtonEvent.UP:
				this.objParams.upParams = null;
				this.objFunctions.upFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_UP, this.addMouseInteraction);
				break;
				
				case ButtonEvent.DOWN:
				this.objParams.downParams = null;
				this.objFunctions.downFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_DOWN, this.addMouseInteraction);
				break;
				
				case ButtonEvent.OVER:
				this.objParams.overParams = null;
				this.objFunctions.overFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_OVER, this.addMouseInteraction);
				break;
				
				case ButtonEvent.OUT:
				this.objParams.outParams = null;
				this.objFunctions.outFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_OUT, this.addMouseInteraction);
				break;
				
				case ButtonEvent.DOUBLE_CLICK:
				this.mcButton.doubleClickEnabled = false;
				this.objParams.doubleClickParams = null;
				this.objFunctions.doubleClickFunction = null;
				this.mcButton.removeEventListener(MouseEvent.DOUBLE_CLICK, this.addMouseInteraction);
				break;
				
				case ButtonEvent.RELEASE_OUTSIDE:
				this.objParams.releaseOutsideParams = null;
				this.objFunctions.releaseOutsideFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_DOWN, this.checkForReleaseOutside);
				break;
				
				case ButtonEvent.DRAG_OVER:
				this.objParams.dragOverParams = null;
				this.objFunctions.dragOverFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_OVER, this.checkForDragOver);
				break;
				
				case ButtonEvent.DRAG_OUT:
				this.objParams.dragOutParams = null;
				this.objFunctions.dragOutFunction = null;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_OVER, this.checkForDragOut);
				break;
				
				case ButtonEvent.WHILE_CLICKED:
				this.objParams.whileClickedParams = null;
				this.objFunctions.whileClickedFunction = null;
				this.numDelay = 500;
				this.mcButton.removeEventListener(MouseEvent.MOUSE_DOWN, this.initiateClickedInterval);
				this.clickedInterval = null;
				break;
			}
		}
		
		// internal functions
		private function addMouseInteraction($event:MouseEvent):void
		{
			switch($event.type)
			{
				case "click":
				this.mcButton.addEventListener(ButtonEvent.CLICK, this.objFunctions.clickFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.CLICK, this.objParams.clickParams));
				break;
				
				case "mouseUp":
				this.mcButton.addEventListener(ButtonEvent.UP, this.objFunctions.upFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.UP, this.objParams.upParams));
				break;
				
				case "mouseOver":
				this.mcButton.addEventListener(ButtonEvent.OVER, this.objFunctions.overFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.OVER, this.objParams.overParams));
				break;
				
				case "mouseDown":
				this.mcButton.addEventListener(ButtonEvent.DOWN, this.objFunctions.downFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.DOWN, this.objParams.downParams));
				break;
				
				case "mouseOver":
				this.mcButton.addEventListener(ButtonEvent.OUT, this.objFunctions.outFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.OUT, this.objParams.outParams));
				break;
				
				case "doubleClick":
				this.mcButton.addEventListener(ButtonEvent.DOUBLE_CLICK, this.objFunctions.doubleClickFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.DOUBLE_CLICK, this.objParams.doubleClickParams));
				break;
			}
		}
		
		// release outside functions
		private function checkForReleaseOutside($event:MouseEvent):void
		{
			this.mcButton.parent.stage.addEventListener(MouseEvent.MOUSE_UP, this.buttonReleaseOutside);
		}
		private function buttonReleaseOutside($event:MouseEvent):void
		{
			this.mcButton.parent.stage.removeEventListener(MouseEvent.MOUSE_UP, this.buttonReleaseOutside);
			if ($event.target.name != this.mcButton.name) {
				this.mcButton.addEventListener(ButtonEvent.RELEASE_OUTSIDE, this.objFunctions.releaseOutsideFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.RELEASE_OUTSIDE, this.objParams.releaseOutsideParams));
			}
		}
		// drag over function
		private function checkForDragOver($event:MouseEvent):void
		{
			if ($event.buttonDown) {
				this.mcButton.addEventListener(ButtonEvent.DRAG_OVER, this.objFunctions.dragOverFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.DRAG_OVER, this.objParams.dragOverParams));
			}
		}
		// drag out function
		private function checkForDragOut($event:MouseEvent):void
		{
			if ($event.buttonDown) {
				this.mcButton.addEventListener(ButtonEvent.DRAG_OUT, this.objFunctions.dragOutFunction);
				this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.DRAG_OUT, this.objParams.dragOutParams));
			}
		}
		// while clicked functions
		private function initiateClickedInterval($event:MouseEvent):void
		{
			this.mcButton.addEventListener(MouseEvent.MOUSE_UP, this.stopClickInterval);			
			this.clickedInterval.start({delay:this.numDelay});
		}
		private function stopClickInterval($event:MouseEvent):void
		{
			this.clickedInterval.stop();
			this.mcButton.removeEventListener(MouseEvent.MOUSE_UP, this.stopClickInterval);
		}
		private function timerHandler():void
		{
			this.mcButton.addEventListener(ButtonEvent.WHILE_CLICKED, this.objFunctions.whileClickedFunction);
			this.mcButton.dispatchEvent(new ButtonEvent(ButtonEvent.WHILE_CLICKED, this.objParams.whileClickedParams));
		}
		/*
		
		
		properties
		
		
		*/
		
		/**
		 * Enales/disables the button
		 * @param $bolEnabled
		 * 
		 */		
		public function set enabled($bolEnabled:Boolean):void
		{
			this.mcButton.enabled = $bolEnabled;
		}
		public function get enabled():Boolean
		{
			return this.mcButton.enabled;
		}
		/**
		 * Returns a reference to the display object added int eh constructor
		 * @return 
		 * 
		 */		
		public function get child():*
		{
			return this.mcButton;
		}
	}
}